//
// Created by wyh on 2025-06-14 16:09.
//
#include <iostream>
#include "utility/option.h"

using namespace std;
using namespace wyh::utility;

void Option::add(const std::string &opt, Option::Type type)
{
    m_opts[opt] = type;
}

Option::Type Option::type(const std::string &opt) const
{
    auto it = m_opts.find(opt);
    if (it == m_opts.end())
    {
        return OPT_UNKNOWN;
    }
    return it->second;
}

void Option::parse(int argc, char **argv)
{
    for (int i = 1; i < argc; i++)
    {
        string arg = argv[i];
        cout << i << ":" << arg << endl;
        if (arg.substr(0, 1) != "-")
        {
            //忽略普通参数
            continue;
        }

        if (arg.substr(0, 2) == "--")
        {
            //长参数
            string str = arg.substr(2);
            auto pos = str.find("=");
            if (pos != string::npos)
            {
                //找到=
                string opt = str.substr(0, pos);
                string val = str.substr(pos + 1);
                switch (type(opt))
                {
                    case OPT_NO:
                        throw logic_error("no argument option:" + opt);
                        break;
                    case OPT_REQUIRED:
                    case OPT_OPTIONAL:
                        m_args[opt] = val;
                        break;
                    default:
                        break;
                }
            }
            else
            {
                //没找到=
                switch (type(str))
                {
                    case OPT_NO:
                    case OPT_OPTIONAL:
                        m_args[str] = "";
                        break;
                    case OPT_REQUIRED:
                    {
                        if (i + 1 >= argc)
                        {
                            throw logic_error("option required argument:" + str);
                        }
                        string val = argv[i + 1];
                        if (val.substr(0, 1) == "-")
                        {
                            throw logic_error("option missing argument:" + str);
                        }
                        m_args[str] = val;
                        i += 1;
                        break;
                    }
                    default:
                        break;
                }
            }
        }
        else
        {
            //短参数
            string opt = arg.substr(1, 1);
            switch (type(opt))
            {
                case OPT_NO:
                    if (arg.length() > 2)
                    {
                        for (int k = 1; k < arg.length(); k++)
                        {
                            string o(1, arg[k]);
                            if (type(o) != OPT_UNKNOWN)
                            {
                                continue;
                            }
                            m_args[opt] = "";
                        }
                    }
                    else
                    {
                        m_args[opt] = "";
                    }
                    break;
                case OPT_OPTIONAL:
                {
                    if (arg.length() > 2)
                    {
                        m_args[opt] = arg.substr(2);
                    }
                    else
                    {
                        m_args[opt] = "";
                    }
                    break;
                }
                case OPT_REQUIRED:
                {
                    if (i + 1 > argc)
                    {
                        throw logic_error("option required argment:" + opt);
                    }
                    string val = argv[i + 1];
                    if (val.substr(0, 1) == "-")
                    {
                        throw logic_error("option missing argment:" + opt);
                    }
                    m_args[opt] = val;
                    i++;
                    break;
                }
                default:
                    break;
            }
        }
    }
}

void Option::show() const
{
    for (auto pair: m_args)
    {
        cout << pair.first << ":" << pair.second << endl;
    }
}

bool Option::has(const std::string &opt) const
{
    if (m_opts.find(opt) == m_opts.end())
    {
        return false;
    }

    return m_args.find(opt) != m_args.end();
}

Value Option::get(const std::string &opt)
{
    auto it = m_opts.find(opt);
    if (it == m_opts.end())
    {
        return Value((char *) "");
    }

    switch (type(opt))
    {
        case OPT_NO:
        {
            return Value(m_args.find(opt)!=m_args.end());
        }
        case OPT_OPTIONAL:
        case OPT_REQUIRED:
        {
            return Value(m_args[opt]);
        }
        default:
            break;
    }
    return Value((char*)"");
}
